#include "HeaderFile/SerialPort.hpp"
#include <iostream>
#include <iomanip>  // 需要包含这个头文件用于std::setw, std::setfill
#include <thread>
#include <chrono>

std::atomic<bool> running{true};
// 案例一，将x,y轴转换为高低位
void uint16ArrayToLittleEndianCase(){
    SerialPort serial;
    SerialPort::Config config;

    if(serial.open(config)){
        std::cout << "串口打开成功" << std::endl;

        std::vector<uint16_t> values = {0x1234, 0x5678};
        auto bytes = serial.uint16ArrayToLittleEndian(values);
        std::cout << "小端序输出: ";
        for (uint8_t byte : bytes) {
        std::cout << std::hex << std::setw(2) << std::setfill('0') 
                  << static_cast<int>(byte) << " ";
        }
        std::cout << std::dec << std::endl;
    }

    serial.close();
}

// 案例二 发送串口
void writeWithChecksumCase(){

    SerialPort serial;
    SerialPort::Config config;
    
    // 配置串口，这个是给虚拟机配置的，jetsonNano我配置在.hpp里面了
    // config.device = "/dev/ttyUSB0";  // 根据实际情况修改
    // config.baudRate = 115200;
    
    // 打开串口
    if (serial.open(config)) {
        std::cout << "串口打开成功" << std::endl;
        
        // 发送十六进制数据
        // | 0x51 | x(l) | x(h) | y(l) | y(h) | crc |
        std::vector<uint8_t> hexData = {0x51, 0x02, 0x03, 0xFF, 0xAA, 0x55};
        
        if (serial.writeWithChecksum(hexData)) {
            std::cout << "发送十六进制数据成功: ";
            for (uint8_t byte : hexData) {
                printf("%02X ", byte);
            }
            std::cout << std::endl;
        } else {
            std::cout << "发送失败: " << serial.getLastError() << std::endl;
        }
        
        serial.close();
    } else {
        std::cout << "串口打开失败: " << serial.getLastError() << std::endl;
    }

}
// 案例三 异步读取
void startAsyncReadCase(){
    SerialPort serial;
    SerialPort::Config config;
    
    // 配置串口，这个是给虚拟机配置的，jetsonNano我配置在.hpp里面了
    // config.device = "/dev/ttyUSB0";  // 根据实际情况修改
    // config.baudRate = 115200;
    
    // 打开串口
    if (serial.open(config)) {
        std::cout << "串口打开成功" << std::endl;
        serial.startAsyncRead([](const std::vector<uint8_t>& data) {
            // 添加调试信息
            std::cout << "[DEBUG] 回调被调用，收到 " << data.size() << " 字节" << std::endl;
            
            // 改进的十六进制显示
            std::cout << "hex(" << data.size() << " bytes): ";
            for (auto byte : data) {
                std::cout << std::hex << std::setw(2) << std::setfill('0') 
                        << static_cast<int>(byte) << " ";
            }
            std::cout << std::dec << std::endl;
            std::cout.flush();  // 确保立即输出
        });
        
        std::cout << "开始监听，按回车退出..." << std::endl;
        std::cin.get();
        
        serial.stopAsyncRead();
        
        serial.close();
    } else {
        std::cout << "串口打开失败: " << serial.getLastError() << std::endl;
    }
}

// 案例四 发送装甲板中心点坐标
void armourCenter(){
    SerialPort serial;
    SerialPort::Config config;
    
    // 发送十六进制数据
        // | 0x51 | x(l) | x(h) | y(l) | y(h) | crc |
    
    // 打开串口
    if (serial.open(config)) {
        std::cout << "串口打开成功" << std::endl;
        //模拟中心点x,y
        std::vector<uint16_t> values = {0x1234, 0x5678};

        std::vector<uint8_t> bytes = serial.uint16ArrayToLittleEndian(values);
        bytes.insert(bytes.begin() , 0x51);
        
        if (serial.writeWithChecksum(bytes)) {
            std::cout << "发送十六进制数据成功: ";
            for (uint8_t byte : bytes) {
                printf("%02X ", byte);
            }
            std::cout << std::endl;
        } else {
            std::cout << "发送失败: " << serial.getLastError() << std::endl;
        }

        serial.close();
    } else {
        std::cout << "串口打开失败: " << serial.getLastError() << std::endl;
    }
}

// 案例五：异步监听 + 定时发送（持续运行）
void asyncReadWithPeriodicSend() {
    SerialPort serial;
    SerialPort::Config config;
    
    // 配置串口
    // config.device = "/dev/ttyUSB0";
    // config.baudRate = 115200;

    std::vector<uint8_t> sendData = {0x51, 0x02, 0x03, 0xFF, 0xAA};
    
    // 打开串口
    if (serial.open(config)) {
        std::cout << "串口打开成功" << std::endl;
        
        // 启动异步读取
        serial.startAsyncRead([](const std::vector<uint8_t>& data) {
            std::cout << "[接收] hex(" << data.size() << " bytes): ";
            for (auto byte : data) {
                std::cout << std::hex << std::setw(2) << std::setfill('0') 
                        << static_cast<int>(byte) << " ";
            }
            std::cout << std::dec << std::endl;
            std::cout.flush();
        });
        
        std::cout << "开始监听，每秒自动发送数据，按 Ctrl+C 退出..." << std::endl;
        

        // 无限循环发送
        while (true) {
            // 准备发送数据
            std::vector<uint8_t> sendData = {0x51, 0x02, 0x03, 0xFF, 0xAA};
            
            if (serial.writeWithChecksum(sendData)) {
                for (uint8_t byte : sendData) {
                    printf("%02X ", byte);
                }
                std::cout << std::endl;
            } else {
                std::cout << "[发送失败] " << serial.getLastError() << std::endl;
            }
            
            // 等待1秒
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        
        // 清理（正常情况下不会执行到这里，除非有异常）
        serial.stopAsyncRead();
        serial.close();
    } else {
        std::cout << "串口打开失败: " << serial.getLastError() << std::endl;
    }
}

// 案例六：高速回显（收到数据后立即添加帧尾0xAA并发送回去）
void highSpeedEcho() {
    SerialPort serial;
    SerialPort::Config config;
    
    // 配置串口
    // config.device = "/dev/ttyUSB0";
    // config.baudRate = 115200;
    
    if (serial.open(config)) {
        std::cout << "串口打开成功，开始高速回显模式..." << std::endl;
        
        // 启动异步读取，在回调中立即回显
        serial.startAsyncRead([&serial](const std::vector<uint8_t>& data) {
            // 快速构造回显数据：原数据 + 帧尾0xAA
            std::vector<uint8_t> echoData = data;
            echoData.push_back(0xAA);
            
            // 立即发送（使用 write 而不是 writeWithChecksum 以减少开销）
            // serial.write(echoData);
            // 无锁快速写入方法（用于更高性能）
            serial.writeFast(echoData);
            
            // 可选：只在调试时输出（注释掉以提高性能）
            // std::cout << "[回显] " << data.size() << " bytes -> " << echoData.size() << " bytes" << std::endl;
        });
        
        std::cout << "高速回显运行中，按 Ctrl+C 退出..." << std::endl;
        
        // 主线程保持运行
        while (true) {
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    } else {
        std::cout << "串口打开失败: " << serial.getLastError() << std::endl;
    }
}

// 案例7 ： 解析陀螺仪数据

// 共享数据、实时更新
std::vector<uint8_t> g_receivedData; // 存储接收到的数据
std::mutex g_dataMutex; // 保护共享数据的互斥锁
std::atomic<bool> g_newDataAvailable{false}; // 新数据到达标志（原子操作）

void parseGyroData(){
    SerialPort serial;
    SerialPort::Config config;
    
    if (serial.open(config)) {
        std::cout << "串口打开成功" << std::endl;
        
        // 🔥 步骤1：设置异步读取回调函数
        serial.startAsyncRead([](const std::vector<uint8_t>& data) {
            // 这个函数在另一个线程中执行（当数据到达时自动调用）
            
            // 🔒 步骤2：加锁保护共享数据
            {
                std::lock_guard<std::mutex> lock(g_dataMutex);
                
                // 步骤3：更新共享数据
                g_receivedData = data;           // 保存最新数据
                g_newDataAvailable = true;       // 设置新数据标志
            } // 🔓 这里自动释放锁（lock_guard超出作用域）
            
            // 实时显示接收到的数据（不需要加锁，因为只是读取显示）
            // std::cout << "[接收] hex(" << data.size() << " bytes): ";
            // for (auto byte : data) {
            //     printf("%02X ", byte);
            // }
            // if(!data.empty()){
            //     std::cout << std::endl;
            // }
        });
        
        std::cout << "开始监听，每秒自动发送数据..." << std::endl;
        

        while (true) {

            std::vector<uint8_t> sendData = {};

            // 🔥 步骤：检查并处理新数据（主线程）
            if (g_newDataAvailable) {
                std::vector<uint8_t> currentData;
                
                // 🔒 步骤：加锁读取共享数据
                {
                    std::lock_guard<std::mutex> lock(g_dataMutex);
                    currentData = g_receivedData;    // 复制数据到局部变量
                    g_newDataAvailable = false;      // 重置标志
                } // 🔓 自动释放锁
                
                // 处理数据（不需要加锁，因为使用的是局部副本）
                if(currentData.size() < 11){
                    std::cout << "没有";
                }
                auto gyro = serial.parseGyroFrame(currentData);
                if (gyro.valid) {
                    std::cout << "Roll=" << gyro.roll
                              << " Pitch=" << gyro.pitch
                              << " Yaw=" << gyro.yaw
                              << " Tick=" << gyro.tick << "ms\n";
                              sendData = currentData;
                    std::cout << "解析成功" << std::endl;
                }

            }

            if (serial.writeWithChecksum(sendData) && !sendData.empty()) {
                std::cout << "发送十六进制数据成功: ";
                for (uint8_t byte : sendData) {
                    printf("%02X ", byte);
                }
                std::cout <<  std::endl;
            }
            

        }
        
        serial.stopAsyncRead();
        serial.close();
    }
}

int main() {
    // uint16ArrayToLittleEndianCase();
    // writeWithChecksumCase();
    // startAsyncReadCase();
    // armourCenter();
    // asyncReadWithPeriodicSend();
    // highSpeedEcho();
    parseGyroData();
    return 0;
}
